
#include <BVectorArray>
#include <BCoordArray>
#include "member_BSphere.h"

using namespace BWE;

member_BSphere::member_BSphere(BSphere* sphere)
{
	boss = sphere;
	radius = 0;
	sides = 24;
	segments = 24;
	prepare();
}
member_BSphere::~member_BSphere()
{

}

void member_BSphere::prepare()
{
	coses.resize(sides + 1);
	sines.resize(sides + 1);

	float srh = PI2 / sides;
	for (int i = 0; i < sides + 1; i++)
	{
		float angle = srh * (i + 1);
		coses[i] = cos(angle);
		sines[i] = sin(angle);
	}

}
bool member_BSphere::rebuild()
{
	//add sewn edges.
	int column = sides + 1;
	int numVertex = column * (segments - 1) + 2;

	BVectorArray* vertices = boss->vertices();
	BVectorArray* normals = boss->normals();
	BCoordArray* texCoords = boss->texCoords();

	if (!vertices || vertices->size() != numVertex)
	{
		vertices = new BVectorArray(numVertex);
		normals = new BVectorArray(numVertex);
		texCoords = new BCoordArray(numVertex);
		boss->setVertices(vertices);
		boss->setNormals(normals);
		boss->setTexCoords(texCoords);
	}
	boss->clearPrimitives();

	{
		float sth = 1.0f / sides;	//texcoord step hor
		float stv = 1.0f / segments;	//texcoord step ver
		float angleRateV = PI / segments;
		for (int r = 0; r < segments - 1; r++)
		{
			float angleV = angleRateV * (r + 1);
			float nz = cos(angleV);
			float sinV = sin(angleV);
			int pos = r * column;
			for (int c = 0; c < column; c++)
			{
				float nx = coses[c] * sinV;
				float ny = sines[c] * sinV;
				BVector normal(nx, ny, nz);
				vertices->set(pos + c, normal * radius);
				normals->set(pos + c, normal);
				texCoords->set(pos + c, BCoord(sth * c, stv * r));
			}
		}

		int top = vertices->size() - 1 - 1;
		(*vertices)[top] = BVector(0, 0, radius);
		(*normals)[top] = BVector(0, 0, 1);
		(*texCoords)[top] = BCoord(0.5, 0);

		int bottom = vertices->size() - 1;
		(*vertices)[bottom] = BVector(0, 0, -radius);
		(*normals)[bottom] = BVector(0, 0, -1);
		(*texCoords)[bottom] = BCoord(0.5, 1);
	}
	//flank
	BIndexArray* flankIndices = new BIndexArray(sides * (segments - 2) * 4);
	BPrimitive* flankQuads = new BPrimitive(BPrimitive::Quads, flankIndices);
	for (int r = 0; r < segments - 2; r++)
	{
		int head = r * column;
		int pos = r * sides * 4;
		for (int c = 0; c < sides; c++)
		{
			int index0 = head + c;
			int index1 = head + c + 1;
			int index2 = index0 + column;
			int index3 = index1 + column;
			(*flankIndices)[pos + c * 4] = index0;
			(*flankIndices)[pos + c * 4 + 1] = index2;
			(*flankIndices)[pos + c * 4 + 2] = index3;
			(*flankIndices)[pos + c * 4 + 3] = index1;
		}
	}
	boss->addPrimitive(flankQuads);

	//top
	BIndexArray* topIndices = new BIndexArray(sides * 3);
	BPrimitive* topTrigs = new BPrimitive(BPrimitive::Triangles, topIndices);
	{
		int begin = 0;
		int top = vertices->size() - 1 - 1;
		for (int i = 0; i < sides; i++)
		{
			int index0 = begin + i;
			int index1 = index0 + 1;
			topIndices->set(i * 3, index0);
			topIndices->set(i * 3 + 1, index1);
			topIndices->set(i * 3 + 2, top);
		}
	}
	boss->addPrimitive(topTrigs);

	//bottom
	BIndexArray* bottomIndices = new BIndexArray(sides * 3);
	BPrimitive* bottomTrigs = new BPrimitive(BPrimitive::Triangles, bottomIndices);
	{
		int begin = vertices->size() - 1 - 1 - sides - 1;
		int bottom = vertices->size() - 1;
		for (int i = 0; i < sides; i++)
		{
			int index0 = begin + i;
			int index1 = index0 + 1;
			(*bottomIndices)[i * 3] = index0;
			(*bottomIndices)[i * 3 + 1] = bottom;
			(*bottomIndices)[i * 3 + 2] = index1;
		}
	}
	boss->addPrimitive(bottomTrigs);

	return true;
}

